package com.lanyou.esb.cook.proxy.service.push.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import com.lanyou.esb.cook.proxy.dao.Dao;
import com.lanyou.esb.cook.proxy.service.push.Push;

/**
 * 消息推送基类
 * 
 * @author Davey.wu
 */
public abstract class BasePush<T> implements Push<T> {
	private Dao<T> dao;
	/** 保存到DB列表 **/
	protected BlockingQueue<T> COLLECTION_4_DB = new LinkedBlockingQueue<>();
	/** 更新到DB列表 **/
	protected BlockingQueue<T> COLLECTION_4_DB_UPDATE = new LinkedBlockingQueue<>();
	/** 保存到redis列表 **/
	protected BlockingQueue<T> COLLECTION_4_REDIS = new LinkedBlockingQueue<>();

	@Override
	public void push() {
		pushToDB();
		pushToRedis();
	}

	@Override
	public void pushToDB() {
		synchronized (COLLECTION_4_DB) {
			if (COLLECTION_4_DB.isEmpty()) {
				return;
			}
			List<T> list = new ArrayList<>(COLLECTION_4_DB.size());
			T target = null;
			do {
				target = COLLECTION_4_DB.poll();
				if (target == null) {
					break;
				}
				list.add(target);
			} while (target != null);
			if (list.isEmpty()) {
				return;
			}
			try {
				// 保存到数据库
				dao.saveAll(list);
			} catch (Exception e) {
				putToCollection4DB(list);
			}

		}

	}

	@Override
	public void updateToDB() {
		synchronized (COLLECTION_4_DB_UPDATE) {
			if (COLLECTION_4_DB_UPDATE.isEmpty()) {
				return;
			}
			List<T> list = new ArrayList<>(COLLECTION_4_DB_UPDATE.size());
			T target = null;
			do {
				target = COLLECTION_4_DB_UPDATE.poll();
				if (target == null) {
					break;
				}
				list.add(target);
			} while (target != null);
			if (list.isEmpty()) {
				return;
			}
			try {
				// 更新到数据库
				dao.update(list);
			} catch (Exception e) {
				putToCollection4DB4Update(list);
			}

		}

	}

	@Override
	public void pushToRedis() {
		if (COLLECTION_4_REDIS.isEmpty()) {
			return;
		}
		T target = null;
		try {
			do {
				target = COLLECTION_4_REDIS.poll();
				if (target == null) {
					break;
				}
				pushToRedis(target);
			} while (true);
		} catch (Exception e) {
			if (target != null) {
				try {
					COLLECTION_4_REDIS.put(target);
				} catch (InterruptedException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		}

	}

	@Override
	public void putToCollection4DB(List<T> list) {
		if (list == null || list.isEmpty()) {
			return;
		}
		synchronized (COLLECTION_4_DB) {
			try {
				for (T t : list) {
					COLLECTION_4_DB.put(t);
				}
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

	@Override
	public void putToCollection4DB(T target) {
		if (target == null) {
			return;
		}
		synchronized (COLLECTION_4_DB) {
			try {
				COLLECTION_4_DB.put(target);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

	@Override
	public void putToCollection4DB4Update(List<T> list) {
		if (list == null || list.isEmpty()) {
			return;
		}
		synchronized (COLLECTION_4_DB_UPDATE) {
			try {
				for (T t : list) {
					COLLECTION_4_DB_UPDATE.put(t);
				}
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

	@Override
	public void putToCollection4DB4Update(T target) {
		if (target == null) {
			return;
		}
		synchronized (COLLECTION_4_DB_UPDATE) {
			try {
				COLLECTION_4_DB_UPDATE.put(target);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

	@Override
	public void putToCollection4Redis(List<T> list) {
		if (list == null || list.isEmpty()) {
			return;
		}
		synchronized (COLLECTION_4_REDIS) {
			try {
				for (T t : list) {
					COLLECTION_4_REDIS.put(t);
				}
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

	@Override
	public void putToCollection4Redis(T target) {
		if (target == null) {
			return;
		}
		synchronized (COLLECTION_4_REDIS) {
			try {
				COLLECTION_4_REDIS.put(target);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	public Dao<T> getDao() {
		return dao;
	}

	public void setDao(Dao<T> dao) {
		this.dao = dao;
	}

}
